// ============================================================================
// IPC服务层 - 统一的IPC通信管理
// ============================================================================

import { IPCResponse } from '../../shared/types'
import { logger } from '../utils/logger'

/**
 * IPC服务类 - 提供统一的IPC通信接口
 * 解决循环依赖和重复调用问题
 */
export class IPCService {
  private static instance: IPCService
  private electronAPI: any
  private requestCache = new Map<string, { data: any; timestamp: number }>()
  private pendingRequests = new Map<string, Promise<any>>()
  private readonly CACHE_TTL = 5000 // 5秒缓存
  private serviceLogger = logger

  private constructor() {
    this.electronAPI = (window as any).electronAPI
    if (!this.electronAPI) {
      throw new Error('ElectronAPI not available. Check preload script.')
    }
  }

  /**
   * 获取单例实例
   */
  static getInstance(): IPCService {
    if (!IPCService.instance) {
      IPCService.instance = new IPCService()
    }
    return IPCService.instance
  }

  /**
   * 带缓存和去重的IPC调用
   */
  async invoke<T = any>(channel: string, ...args: any[]): Promise<T> {
    const cacheKey = `${channel}:${JSON.stringify(args)}`

    // 某些操作不应该被缓存（如验证、删除等）
    const shouldSkipCache = this.shouldSkipCache(channel)

    if (!shouldSkipCache) {
      // 检查缓存
      const cached = this.requestCache.get(cacheKey)
      if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
        this.serviceLogger.debug(`Cache hit for ${channel}`)
        return cached.data
      }
    }

    // 检查是否有相同的请求正在进行
    const pending = this.pendingRequests.get(cacheKey)
    if (pending) {
      this.serviceLogger.debug(`Request deduplication for ${channel}`)
      return pending
    }

    // 创建新请求
    const requestPromise = this.executeRequest<T>(channel, ...args)
    this.pendingRequests.set(cacheKey, requestPromise)

    try {
      const result = await requestPromise

      // 缓存结果（如果允许缓存）
      if (!shouldSkipCache) {
        this.requestCache.set(cacheKey, {
          data: result,
          timestamp: Date.now()
        })
      }

      return result
    } catch (error) {
      this.serviceLogger.error(`IPC call failed: ${channel}`, error)
      throw error
    } finally {
      // 清理pending请求
      this.pendingRequests.delete(cacheKey)
    }
  }

  /**
   * 判断是否应该跳过缓存
   */
  private shouldSkipCache(channel: string): boolean {
    // 这些操作不应该被缓存
    const noCacheChannels = [
      'login:validate',
      'login:delete-account',
      'login:delete-invalid-accounts',
      'task:start',
      'task:stop',
      'config:update',
      'scheduler:create-task',
      'scheduler:update-task',
      'scheduler:delete-task',
      'scheduler:execute-now',
      'scheduler:start',
      'scheduler:stop',
      'workflow:execute'
    ]

    return noCacheChannels.includes(channel)
  }

  /**
   * 执行实际的IPC请求
   */
  private async executeRequest<T>(channel: string, ...args: any[]): Promise<T> {
    const response: IPCResponse<T> = await this.electronAPI.invoke(channel, ...args)
    if (!response.success) {
      const error = new Error(response.error?.message || 'IPC call failed')
      error.name = response.error?.code || 'IPCError'
      throw error
    }
    return response.data as T
  }

  /**
   * 清理缓存
   */
  clearCache(pattern?: string): void {
    if (pattern) {
      for (const key of this.requestCache.keys()) {
        if (key.includes(pattern)) {
          this.requestCache.delete(key)
        }
      }
    } else {
      this.requestCache.clear()
    }
  }

  /**
   * 事件监听
   */
  on(channel: string, callback: (...args: any[]) => void): void {
    this.electronAPI.on(channel, callback)
  }

  /**
   * 移除事件监听
   */
  off(channel: string, callback: (...args: any[]) => void): void {
    this.electronAPI.off(channel, callback)
  }

  /**
   * 一次性事件监听
   */
  once(channel: string, callback: (...args: any[]) => void): void {
    this.electronAPI.once(channel, callback)
  }

  /**
   * 移除所有监听器
   */
  removeAllListeners(channel?: string): void {
    this.electronAPI.removeAllListeners(channel)
  }
}

/**
 * 全局IPC服务实例
 */
export const ipcService = IPCService.getInstance()
